[10/10/99]Ŀ
----     <-- Safedisc Cracking Tutorial by Tola[AmoK] -->     ---Ĵ


 Inhalt - Deutsche Version

    I.  Einleitung
        1. ber dieses Tutorial
        2. ber Safedisc
        3. Erkennen von Safedisc-geschtzten Programmen
        4. Bentigte Tools / Kenntnisse
            a) Assembler
            b) PE-Dateiformat
            c) SoftIce fr Win9x
            d) FrogSice 0.31
            e) ProcDump 1.5
            f) ADump
            g) mitgelieferte Tools
            h) Zeit und Nerven
    II. Cracken des Programmes
        1. Vorbereitung
        2. Dumpen der EXE-Datei
        3. Die Importtabelle
            a) Was Safedisc damit angestellt hat
            b) Reparieren der Importtabelle
            c) Kompatibilittsprobleme
    III.Schluwort / Thanks & Greetings / Autorkontakt

 Tutorial

    I. Einleitung

       1. ber dieses Tutorial

          Dieses Tutorial behandelt das Cracken von Programmen
          (vornehmlich Spielen), die mit Safedisc von C-Dilla
          geschtzt sind. Ich beziehe mich hierbei auf die
          neue Version von Safedisc, die seit einigen Wochen
          verwendet wird. Aufgrund einiger Vernderungen
          funktioniert weder der Generic Safedisc Crack von
          Laxity, noch die in Black Checks Tutorial beschriebene
          Methode zum Erstellen einer lauffhigen EXE-Datei.
          Obwohl dies mein erstes Tutorial ist, habe ich versucht,
          alles so verstndlich und ausfhrlich wie mglich zu
          erklren. Leider mu ich einiges als bekannt voraussetzen,
          da die Erklrungen hierzu den Rahmen dieses Tutorials
          sprengen wrden (dies bezieht sich z.B. auf die Struktur
          des PE-Dateiformats oder der Importtabelle).

       2. ber Safedisc.

          Safedisc ist ein kommerzieller Kopierschutz fr CD-Roms,
          der mittlerweile in nahezu jedem neu erscheinenden Spiel
          verwendet wird. Folgende Features bieten, in den Augen
          des Herstellers, einen starken Schutz gegen Vervielfltigung
          der geschtzten CDs:
          - Auf jeder CD befindet sich eine digitale Signatur, die
            mit normalen Mitteln nicht kopiert werden kann. Am
            Anfang der CD (ca. in den ersten zwei Minuten) finden
            sich eine Menge Lesefehler, die eine 1:1 Kopie ver-
            hindern sollen. Mit spezieller Brennsoftware (z.B.
            Nero oder CDRWin) lassen sich die CDs zwar dennoch
            kopieren, das Spiel wird jedoch trotzdem nicht starten.
            --> Zum Cracken wird die Original-CD bentigt!
          - Die auszufhrende EXE-Datei ist teilweise verschlsselt
            und wird durch einen Loader, der die Signatur der CD
            berprft, entschlsselt und gestartet. Verschlsselte
            Dateien besitzen das Suffix .ICD.
          - Durch Anti-Debugging-Tricks (Jumps in andere Instruktio-
            nen, um das Disassemblieren zu verhindern, sowie ver-
            schiedene Methoden der Debuggererkennung) sollen
            Reverse Engineering des Loaders und der geschtzten
            EXE-Datei verhindern.

       3. Erkennen von Safedisc-geschtzten Programmen

          Das Erkennen eines Safedisc-Kopierschutzes ist sehr
          einfach:
          - Auf der CD (oder im Installationsverzeichnis) befinden
            sich folgende Dateien:
            CLCD16.DLL, CLCD32.DLL, CLOKSPL.EXE, DPLAYERX.DLL
            sowie eine oder mehrere Dateien mit numerischem
            Namen und der Endung .016 oder .256 (dies sind die
            Bitmaps, die beim Ladevorgang angezeigt werden) und
            eine Datei mit der Endung .TMP (meist 00000001.TMP)
          - Die EXE-Datei, die das Spiel startet, ist ca. 300 KB
            gro, es existiert eine weitere Datei mit gleichen
            Namens mit der Endung .ICD
          - Die CD lt sich aufgrund vieler Lesefehler nicht
            kopieren

       4. Bentigte Tools / Kenntnisse

          Zur Erstellung einer lauffhigen EXE-Datei werden einige
          wichtige Tools bentigt, die ich im folgenden kurz vor-
          stellen werde. Fast alle werden irgendwo im Internet
          zum Download angeboten, eine gute Adresse ist z.B.
          Programmer's Tools (w3.to/protools).
        
       a) Assembler

          Zum besseren Verstndnis dieses Tutorials solltest du
          relativ gute Assemblerkenntnisse besitzen.

       b) PE-Dateiformat
          
          Da dieses Thema mitunter sehr komplex ist, kann ich
          leider nicht alles in diesem Tutorial erklren. Es
          gibt jedoch viele gute Informationen zu PE-Dateien
          im Internet.

       c) SoftIce fr Win9x

          Das Tool schlechthin. Ich empfehle dir, die neueste
          Version von Softice zu besorgen (z.Zt. 4.0), eine
          etwas ltere Version sollte aber auch reichen.

       d) FrogSice 0.31

          Dieses Tool erkennt Anti-Softice-Tricks und versucht
          nach Mglichkeit, Softice "unsichtbar" zu machen.
          Ohne dieses Tool wrde der sich Aufwand zum Cracken
          von Safedisc-geschtzten Spielen drastisch erhhen!
          Zu haben ist es bei www.thepentagon.com/frog_s_print

       e) ProcDump 1.5

          Die Aufgabe, EXE-Dateien vom RAM auf die Festplatte
          zu schreiben (dumpen), wird uns von diesem Programm
          abgenommen. Weiterhin knnen damit wichtige Details
          der EXE-Dateien eingesehen und editiert werden.
          Es sollte bei procdump32.cjb.net in der neuesten
          Version zum Download bereitstehen.

       f) ADump

          ADump ist ein sog. Dumper fr Softice. Das Programm
          stellt einen Speicherbereich bereit, auf den wir
          von Softice aus zugreifen knnen, um dort z.B.
          Daten zwischenzuspeichern. Diese knnen anschlieend
          in eine Datei geschrieben werden.

       g) Mitgelieferte Tools

          In dem Archiv dieses Tutorials befinden sich zwei
          kleine Programme (GetAddr.exe und RepImp.exe), die
          bentigt werden, um die Importtabelle zu reparieren
          (dazu spter mehr). Die beiden Programme kannst du
          dir gerne genauer ansehen, wenn du den Sourcecode
          haben mchtest (extrem schlecht kommentiert ;), email
          mir. Ihre Benutzung wird in II.2.c) erklrt.
       
       h) Zeit und Nerven

          Werden sptestens bentigt, wenn es um das reparieren
          der Importtabelle geht.

    II. Cracken des Programmes

        Was zu beachten ist:
        - Im Laufe des Tutorials werden des fteren Speicher-
          adressen u.. genannt. Diese beziehen sich auf
         das Spiel, welches ich fr dieses Tutorial benutzt
          habe, und knnen (oder besser werden) bei dir
          andere Werte haben.
        - Es ist sinnvoll, sich einige Adressen und Werte
          aufzuschreiben, um sie beim Cracken immer vor
          Augen zu haben. Zu diesem Zweck habe ich eine
          Vorlage erstellt (template.rtf), in die alle
          wichtigen Daten eingetragen werden knnen.
        Ok, das wichtigste ist gesagt worden, aus geht's!

       1. Vorbereitung

          Bevor wir mit der eigentlichen Arbeit beginnen, mssen
          wir einige Informationen ber die zu crackende Datei
          sammeln.
          - Der Entry Point
            Die Programmausfhrung startet an der Adresse, die
            durch den Program Entry Point angegeben wird.
            Wir bentigen den Entry Point der Datei XXX.ICD
            (XXX steht hier fr den Namen der Datei).
            Er kann leicht mit dem PE-Editor von ProcDump
            herausgefunden werden. Im Beispiel von "Rogue Spear"
            war es 0029D150.
            ! --> Der Entry Point ist eine relative virtuelle
                  Adresse (im Folgenden kurz RVA genannt).
                  RVAs werden in PE-Files sehr hufig benutzt.
                  Eine RVA beschreibt eine Speicheradresse,
                  deren Basisadresse wir nicht kennen. Um
                  die lineare Speicheradresse zu erhalten,
                  mu die Basisadresse auf die RVA aufaddiert
                  werden. In diesem Fall wre dies die
                  "Image Base" der EXE-Datei, die wir ebenfalls
                  im PE-Editor von ProcDump finden.
            Die Image Base war 00400000, die Programmausfhrung
            beginnt also bei der linearen Adresse 0069D150.
          - Die .rdata Section
            Mit diesem Teil der Datei werden wir uns spter noch
            ausfhrlich beschftigen mssen. Wir knnen uns
            jetzt jedoch schon einmal die Daten "Virtual Offset"
            (RVA!) und "Virtual Size" aufschreiben (finden sich
            unter "Sections" im PE-Editor). In dieser Section
            befindet sich fr gewhnlich die Importtabelle der
            EXE-Datei. Der Name .rdata ist jedoch nicht verbind-
            lich! Falls es keine Section mit dem Namen .rdata
            gibt, mut du dir unter "Directory" im PE-Editor
            die RVA der Importtabelle holen und nachsehen, in
            welcher Section sich diese befindet (mir ist bisher
            allerdings noch keine EXE untergekommen, in der
            die Section anders hie). Der Importtabelle entnimmt
            das Betriebssystem, welche Funktionen aus welchen
            DLLs das Programm bentigt, und stellt ihm die
            Adressen dieser Funktionen zur Verfgung. Eine
            genauere Beschreibung kannst du einer guten Dokumen-
            tation des PE-Formats entnehmen.
          - Die Startadresse von ADump
            Bevor wir mit dem Cracken beginnen, mssen wir
            ADump starten. Mit dem Befehl r kann man sich
            die Startadresse des reservierten Speicherbereichs
            anzeigen lassen (STARTOFFS). Notiere diesen Wert.
            Sollte dein Computer abstrzen oder du ADump beenden
            mssen, mut du dir beim nchsten Start die neue
            Startadresse aufschreiben.

       2. Dumpen der EXE-Datei

          Der Worte sind genug gewechselt, lat Taten folgen!
          Wir fangen damit an, die EXE-Datei zu dumpen,
          sie also vom Speicher in eine Datei zu schreiben.
          Wieso? Wenn man das Programm startet, ldt der
          Loader die verschlsselte EXE in den Speicher,
          berprft die CD, entschlsselt die EXE und startet
          sie. Alles, was wir tun mssen, ist abzuwarten,
          bis das Programm gestartet hat, und es dann auf
          die Platte zu schreiben. Hierbei gibt es jedoch
          folgendes zu beachten:
          Um eine "exakte" Kopie der Datei zu erhalten,
          mssen wir sie dumpen, bevor irgendwelche Programm-
          internen Daten gendert werden (z.B. einlesen von
          Konfigurationseinstellungen o..). Dies knnte
          (mu es aber nicht) die Lauffhigkeit der Datei
          beeintrchtigen. Folglich mssen wir das Programm
          bei seinem Entry Point anhalten, also einen Breakpoint
          darauf setzen. Die Vorgehensweise hierbei ist wie
          folgt:
          Starte das Programm. Sobald der Splash-Screen ver-
          schwindet kannst du SoftIce aktivieren und einen
          Breakpoint auf den Entry Point setzen. Beim nchsten
          Start sollte SoftIce an diesem Punkt anhalten.
          Sobald dies geschehen ist, setze EIP auf die Start-
          adresse von ADump und assembliere dort mit SoftIce
          ("a eip") folgenden Befehl:

          "jmp eip"

          Damit erzeugen wir zum einen eine Endlosschleife,
          zum anderen wird die EXE-Datei nicht verndert.
          Verlasse nun SoftIce, starte ProcDump und dumpe
          die Datei XXX.ICD in eine Datei (Rechtsklick auf
          die Datei, Dump (full)).
          Fein, wird haben jetzt eine ausfhrbare Datei,
          sind wir jetzt fertig? Tja, schn wr's. Leider
          wird diese Datei noch nicht funktionieren (du
          kannst es natrlich gerne versuchen). Beim
          Versuch, sie zu starten, erhalten wir eine
          hbsche Fehlermeldung. Nun stehen wir vor einem
          mittelschweren (aber keineswegs unlsbaren)
          Problem.

       3. Die Importtabelle

       a) Was Safedisc damit angestellt hat

          Unser Problem ist die bereits kurz angesprochene
          Importtabelle. Wenn eine Datei mit Safedisc ge-
          schtzt wird, wird die Tabelle so gendert,
          da alle Importe aus den DLLs Kernel32 und User32
          auf eine Safedisc-Funktion zeigen. D.h. wenn
          zum Beispiel eigentlich die Funktion GetVersion
          aus User32 aufgerufen werden soll, wird zuerst
          eine Safedisc-Funktion aufgerufen, die die Adresse
          von GetVersion holt und sie dann aufruft. Dies
          funktioniert mit der gedumpten EXE allerdings
          nicht mehr, da die hierfr zustndige DLL ja
          nicht geladen wird.
          Sehen wir uns einmal den Code beim Entry Point
          der Datei an:

          017F:0069D150  PUSH      EBP                ;Entry Point
          017F:0069D151  MOV       EBP,ESP
          017F:0069D153  PUSH      FF
          017F:0069D155  PUSH      0076AE90
          017F:0069D15A  PUSH      006A0200
          017F:0069D15F  MOV       EAX,FS:[00000000]
          017F:0069D165  PUSH      EAX
          017F:0069D166  MOV       FS:[00000000],ESP
          017F:0069D16D  SUB       ESP,58
          017F:0069D170  PUSH      EBX
          017F:0069D171  PUSH      ESI
          017F:0069D172  PUSH      EDI
          017F:0069D173  MOV       [EBP-18],ESP
          017F:0069D176  CALL      [0075F1C8]         ;Funktionsaufruf

          Normalerweise wre untenstehender CALL ein Aufruf
          der Funktion GetVersion. Die Adresse 0075F1C8 ist
          Teil der Importtabelle. Normalerweise wrde an
          dieser Stelle die Adresse der Funktion GetVersion
          stehen (eingefgt von Windows beim Laden der Datei).
          Wie gesagt, normalerweise. Wenn wir jetzt aber
          in den CALL tracen (F8), stoen wir auf folgendes:

          017F:00AE72A0  PUSHAD
          017F:00AE72A1  PUSH      00000050
          017F:00AE72A6  PUSH      00000000
          017F:00AE72AB  CALL      [00AE72C1]
          017F:00AE72B1  ADD       ESP,08
          017F:00AE72B4  POPAD
          017F:00AE72B5  JMP       [00AE72BB]

          Wir wir hier sehen wird eine weitere Funktion
          aufgerufen (bitte noch nicht reintracen).
          Nachdem diese Funktion ausgefhrt worden ist,
          steht in der Adresse 00AE72BB die Adresse der
          eigentlichen Funktion (GetVersion), die aufge-
          rufen werden sollte. Die Funktion liefert auer-
          dem noch zwei Werte zurck:
          In ECX steht nach Aufruf der Funktion die Adresse
          der ersten Funktion dieser Art. Addiert man
          EDX auf ECX, so erhlt man die Adresse 00AE72A0,
          also die Adresse dieser Funktion. Interessant,
          oder? Wenn du weiter durch die Datei tracest,
          wirst du feststellen, da es noch viele andere
          dieser Funktionen gibt, die jedoch andere Parameter
          an die Safedisc-Funktion bergeben (die Adresse
          der Safedisc-Funktion erhltst du, indem du in
          SoftIce "d 00AE72C1" eingibst, bei mir 00A800C0).
          Die Parameter haben folgende Bedeutung:

          017F:00AE72A1  PUSH      00000000   ;Funktionsnummer
          017F:00AE72A6  PUSH      00000000   ;DLL-Nummer
          017F:00AE72AB  CALL      00A800C0

          Der zweite Parameter gibt an, aus welcher DLL die
          Funktion stammt, 0 bedeutet Kernel32, 1 bedeutet
          User32.
          Die Arbeitsweise der Funktion knnen wir zu unserem
          Vorteil nutzen. Wie wir oben gesehen haben, zeigt
          das Doubleword an der Adresse 0075F1C8 auf die
          gerade besprochene Routine. Wenn diese Referenz
          nun durch die korrekte Adresse der importierten
          Funktion ersetzt werden wrde, sollte das Programm
          eigentlich funktionieren! Das Problem ist, da
          wir die Adresse der richtigen Funktion nicht
          kennen. Sie mu aber irgendwo in der Safedisk-
          Funktion berechnet werden. Also gehen wir in
          die Funktion an Adresse 00A800C0 und tracen solange
          durch (nicht durch die vielen Jumps irritieren
          lassen), bis wir an folgende Stelle gelangen:
        
          017F:00A8064B  MOV       ECX,[EBP-08]
          017F:00A8064E  PUSH      ECX
          017F:00A8064F  MOV       EDX,[EBP+08]
          017F:00A80652  PUSH      EDX
          017F:00A80653  CALL      00A7EE10
          017F:00A80658  ADD       ESP,08
          017F:00A8065B  MOV       [EBP-04],EAX
          017F:00A8065E  JMP       00A80669                                                                                  (JUMP )

          Interessant fr uns ich die Adresse 00A8065B.
          Wenn du dir den Inhalt von EAX anschaust, wirst
          du sehen, da sie auf die Adresse der importierten
          Funktion zeigt! Wunderbar, jetzt mssen wir
          nur noch dafr sorgen, da uns diese Adresse
          erhalten bleibt, da sich der Inhalt EAX noch
          ndern wird. Tracen wir also weiter bis zum
          Ende der Routine, bis wir folgenden Code sehen:

          017F:00A80A96  POP       EDI
          017F:00A80A97  POP       ESI
          017F:00A80A98  POP       EBX
          017F:00A80A99  MOV       ESP,EBP
          017F:00A80A9B  POP       EBP
          017F:00A80A9C  RET
          017F:00A80A9D  INT       3
          017F:00A80A9E  INT       3
          017F:00A80A9F  INT       3

          Wie du siehst, sind am Ende der Funktion noch
          drei Bytes frei. Mehr brauchen wir nicht. Ersetze
          die Befehle an Adresse 00A80A9B durch diese
          Befehlsfolge:

          017F:00A80A9B  MOV       EAX,[EBP-4]
          017F:00A80A9E  POP       EBP
          017F:00A80A9F  RET

          Jetzt liefert die Funktion die richtige Adresse
          der importierten Funktion in EAX zurck.
          Anmerkung --> Bei der alten Safedisc-Version wird
                        die Adresse der aufgerufenen Funk-
                        tion in EAX zurckgegeben, ECX
                        enthlt die Adresse der importierten
                        Funktion. Dieser Schritt ist also
                        nur bei der neuen Version notwendig.

       b) Reparieren der Importtabelle

          Jetzt wird es Zeit, die Importtabelle zu reparieren.
          Hierzu mssen wir einen einfachen Algorithmus
          schreiben, der die falschen Referenzen in der Import-
          tabelle durch die korrekten Adressen der importierten
          Funktionen ersetzt. Vorher mssen wir jedoch heraus-
          finden, wieviele Kernel32 respektive User32 Funktionen
          berhaupt importiert werden. Die referenzierten
          Routinen zur Berechnung und Aufruf der korrekten
          Adresse liegen im Abstand von 25h Bytes vor.
          Trace in eine solche hinein und gib folgendes ein:
          (der Befehlszeiger mu auf PUSHAD stehen)

          "u eip+25*x"

          Wobei x eine beliebige Zahl ist, die du immer weiter
          erhhen mu, bis du bei der letzten Routine angelangt
          bist. Bei mir waren es 5Fh Kernel32 Importe.
          Die Routinen fr die User32 Importe waren 29h Bytes
          von der letzten Kernel32 Routine entfernt.
          Durch gleiches Verfahren wie oben findest du heraus,
          da 28h User32 Import vorhanden sind.
          Schreibe dir diese Werte am besten auf.
          Du kannst die Anzahl der Importe auch mit dem Programm
          "IMPORT.EXE" herausfinden, das du im Archiv dieses
          Tutorials findest. Whle einfach die "XXX.ICX" Datei
          aus und klicke auf "Get Info". Im Verzeichnis der
          ausgewhlten Datei wird nun die Datei "IMPORT.TXT"
          erstellt, die Informationen zu allen importierten
          DLLs enthlt.
          So weit, so gut, jetzt werden wir die Tabelle reparieren.
          Starte das Programm und setze den Befehlszeiger auf
          die Anfangsadresse von ADump. Kopiere dann die
          Importtabelle der Datei in einen Speicherbereich,
          der 1000h Bytes hinter der Startadresse von ADump
          liegt:

          "m 735F000 l 46000 82C19000"
             ^         ^     ^
             |         |     Startadresse von ADump + 1000h
             |         Gre der .rdata Section 
             Adresse der .rdata Section.

          Assembliere dann folgenden Algorithmus:

          01: PUSH        EBX
          02: PUSH        0
          03: CALL        A800C0
          04: ADD         ESP,8
          05: ADD         ECX,EDX
          06: MOV         EDX,735F000
          07: CMP         DWORD PTR [EDX],ECX
          08: JE          EIP+D
          09: INC         EDX
          10: CMP         EDX,735F000 + 46000 - 3
          11: JE          EIP+12
          12: JMP         EIP-D
          13: SUB         EDX,735F000
          14: ADD         EDX,82C19000
          15: MOV         DWORD PTR [EDX],EAX
          16: INC         EBX
          18: CMP         EBX,5F
          19: JBE         82C18000
          20: JMP         EIP

          Erluterungen zum Algorithmus:
          01: EBX enthlt die aktuelle Funktionsnummer,
              mu daher zuerst manuell auf 0 gesetzt werden.
          02: DLL-Nr.
          03: Aufruf der Safedisc-Funktion, um die falsche
              Referenz und die korrekte Adresse zu erhalten
          05: ECX beinhaltet nun die Adresse der falschen
              Referenz. EDX mu vor Start des Algorithmus
              manuell auf 0 gesetzt werden!
          07: Die falsche Referenz wird in der Importtabelle
              gesucht.
          10: Wenn das Ende der .rdata Section erreicht wurde
              (Adresse der Section + Gre - 3), wird abge-
              brochen.
          13: Berechnung der Adresse der falschen Referenz in
              unserer Kopie der .rdata Section.
          15: Hier wird die falsche Referenz durch die korrekte
              Adresse ersetzt.
          16: Nchste Funktion.
          17: berprfung, ob die letzte Funktion bearbeitet
              wurde.
          20: Endlosschleife.

          Nun knnen wir dieses kleine Programm starten (nach-
          dem wir EBX und EDX auf 0 gesetzt haben). Setze
          am besten einen Breakpoint auf Zeile 20, damit
          du weit, wann alle Eintrge ersetzt wurden.
          Wenn der Breakpoint erreicht wird, mut du EBX
          und EDX erneut auf 0 setzen und in Zeile 2 das
          PUSH 0 durch ein PUSH 1 ersetzen und in Zeile
          18 das CMP EBX,5F durch CMP EBX,28 ersetzen, um
          auch die User32 Importe zu bearbeiten. Wenn der
          Breakpoint das zweite mal erreicht ist, kannst
          du das Programm beenden (mit ProcDump killen oder
          einfach einen CALL ExitProcess assemblieren).
          Die oben angegebenen Werte wie Adresse der .rdata
          Section mut du natrlich selbst deinem Programm
          entsprechend ndern.
          Anmerkung --> Es kann eventuell vorkommen, da
                        keine gltige Adresse zurckgelie-
                        fert wird (wenn du z.B. zuvor
                        schon in einen CALL hineingetracest
                        hast). Dies lt sich folgender-
                        maen verhindern: Trace in die
                        Safedisc Funktion, bis du auf
                        folgende Befehle triffst:
                        CMP     EAX,1
                        JNZ     XXXXXXXX
                        Setze an der Adresse des Jumps
                        folgenden Breakpoint:
                        "bpx XXXXXXXX if (eax==1) do "r fl=z;g;"
                        Hierdurch wird automatisch das
                        Zero Flag umgeschaltet, falls
                        EAX doch einmal = 1 sein sollte.
          Jetzt kann die aktualisierte .rdata Section mit
          ADump in eine Datei geschrieben werden:

          "W C:\XXX\XXX\RDATA.BIN 46000 82C19000"

          Die Syntax des Befehls kannst du der ADump Doku-
          mentation entnehmen.
          Nun mssen wir die .rdata Section der gedumpten
          Datei durch die gerade auf Festplatte geschriebene
          Version ersetzen. Schaue hierzu mit ProcDump
          nach, an welchem Offset in der Datei die Section
          beginnt, lsche sie aus der Datei und fge die
          neue Section ein.

       c) Kompatibilittsprobleme

          Damit wren wir eigentlich schon am Ende - das
          Programm luft. Doch leider gibt es noch ein
          Problem:
          Da es dutzende verschiedene Windows Versionen
          gibt, gibt es auch dutzende verschiedene Kernel32
          und User32 DLLs. Schn und gut, das Problem ist
          jedoch, da diese nicht immer an die gleiche
          Adresse im Speicher geladen werden. Die Konse-
          quenz ist, da das gecrackte Programm nur auf
          deinem Betriebssystem laufen wird.
          Um meine Lsung dieses Problems zu beschreiben,
          mu ich etwas weiter ausholen. Es folgt also
          eine kurze Beschreibung des Formats der Import-
          tabelle:

          Wie bereits erwhnt, wird eine Importtabelle
          bentigt, um Funktionen der Windows API oder
          anderer DLLs aufzurufen. Die DLLs knnen an
          unterschiedlichen Adressen geladen sein, die
          nur zur Laufzeit festgestellt werden knnen.
          Die Adressen knnen daher nicht fest einkompi-
          liert werden. Stattdessen verweisen alle
          Funktionsaufrufe in einer PE-Datei auf eine
          Stelle in der Importtabelle, in welche das
          Betriebssystem die aktuelle Adresse der auf-
          zurufenden Funktion eintrgt. Der Aufbau
          der Importtabelle sieht wie folgt aus
          (die erweiterten Mglichkeiten werde ich
          auslassen):

          Die Importtabelle beginnt mit einem Import-
          verzeichnis, welches ein Array von IMAGE_
          IMPORT_DESCRIPTORs darstellt, ein Element
          fr jede importierte DLL. Das Array wird durch
          einen IMAGE_IMPORT_DESCRIPTOR abgeschlossen,
          der komplett mit 0-Bytes gefllt ist.
          Ein IMAGE_IMPORT_DESCRIPTOR ist eine Struktur
          mit folgendem Aufbau:

          OriginalFirstThunk
            Eine RVA (32 Bit), die auf ein nullterminiertes
            Array weiterer RVAs zeigt.

          TimeDateStamp
            32-Bit Timestamp, im Moment uninteressant.

          ForwarderChain
            32-Bit-Index des nchsten Forwarders - uninteressant
            fr uns.

          Name
            Eine 32-Bit RVA zum Namen der DLL (0-terminierter
            String).

          FirstThunk
            Eine 32-Bit RVA zu einem nullterminierten
            Array weiterer RVAs.

          Jeder IMAGE_IMPORT_DESCRIPTOR gibt uns also den
          Namen der DLL sowie zwei RVAs zu zwei Arrays.
          Die Arrays sind beide nullterminiert und bestehen
          aus RVAs, die (fr gewhnlich) auf einen
          IMAGE_IMPORT_BY_NAME zeigen. Die beiden Arrays
          laufen parallel, d.h. sie zeigen auf die gleichen
          IMAGE_IMPORT_BY_NAMEs.

          Diese wiederum bestehen aus einer 16-Bit Zahl
          (Ordinalzahl der Funktion) sowie einem null-
          terminierten String, dem Funktionsnamen.

          Wenn nun ein Programm gestartet wird, sucht das
          Betriebssystem ber das Array, auf das Original-
          FirstThunk zeigt, die Funktionsnamen und schreibt
          die Adressen dieser Funktionen in das Array,
          auf das FirstThunk zeigt. Das Programm kann nun
          ber dieses Array auf die Funktionsadressen
          zugreifen und sie ausfhren. Eben dieses Array
          ist es, das wir mit bereits mit den korrekten
          Adressen gefllt haben.
          Das OS kann also nicht selbst die korrekten
          Adressen einfgen, da auerdem der Eintrag
          OriginalFirstThunk = 0 ist! Die Funktionsnamen
          der Funktionen wurden von Safedisc ebenfalls
          entfernt. Also wie zum Henker bekommt man dieses
          Ding wieder hin?
          Einige Zeit und gute 800 Zeilen Assemblercode
          spter hatte ich eine Lsung gefunden.

          Zur Lsung der Aufgabe schrieb ich zwei Programme:
          - GettAddr
            Dieses Programm liest *alle* Funktionsnamen
            der DLLs Kernel32 und User32 aus zwei Dateien
            (KERNEL32.EXP und USER32.EXP) aus und schreibt
            die fr das jeweilige OS gltigen Funktions-
            adressen in die Dateien KERNEL32.ADR und
            USER32.ADR
          - RepImp
            Dieses Programm bernimmt den greren Teil
            der Arbeit. Es liest die Adressen aus den
            Dateien XXX32.ADR aus und sucht diese in
            der Importtabelle einer angegebenen EXE-Datei.
            Wenn eine bereinstimmung gefunden wird,
            fgt es den Funktionsnamen an das Dateiende
            an und ndert das Array, in das wir zuvor
            die korrekten Adressen geschrieben haben,
            so ab, da es nun auf den Funktionsnamen
            zeigt. Dadurch wird erreicht, da das
            Betriebssystem die Funktionsnamen findet
            und die korrekten Adressen in bereits
            erwhntes Array schreibt.
            Anmerkung --> Diese Methode ist nicht unein-
                          geschrnkt problemlos anzuwenden.
                          Es wird der PE-Header, die Objekt-
                          tabelle und die Dateigre ver-
                          ndert, was *eventuell* zu Pro-
                          blemen fhren kann. Es wre besser,
                          die Funktionsnamen in einen freien
                          Bereich der .rdata Section zu
                          schreiben.
            Es ist ebenfalls mglich, manuell mit einem Hex-
            Editor in der .rdata Section nach einem geeigneten
            Platz fr die Funktionsnamen zu suchen. Das Offset
            dieser Stelle in der .rdata Section kann dann in
            RepImp eingegeben werden, nachdem der Modus von
            "Append" nach "Insert" gendert wurde. Beispiel:
            Die .rdata Section beginnt in der Datei bei
            001F600h, der freie Platz liegt an Offset 001F750h.
            In RepImp mu also als Offset also 150 eingegeben
            werden (immer als Hexadezimalzahl, ohne abschlieendes
            "h" oder hnliches).
            Anmerkung --> Die Insert-Funktion sollte nur dann
                          benutzt werden, wenn die EXE-Datei nach
                          Anwendung der Append-Funktion nicht mehr
                          funktioniert. Ferner sollte sie nur von
                          Personen benutzt werden, die wissen, was
                          sie tun.
          Soweit alles klar? Na, hoffentlich. Um deine gedumpte
          EXE-Datei kompatibel zu machen, mut du nur GetAddr starten
          und die Datei anschlieend mit RepImp bearbeiten.
          Anmerkung --> RepImp vergrert die Datei im "Append"-
                        Modus immer um 32 KB. Du kannst es dabei
                        belassen oder die berflssigen Nullen
                        hinter den Funktionsnamen entfernen.
          Vorsicht: Ich kann keine Garantie auf Fehlerfrei-
          heit der Programme geben. Auerdem knnen beide
          Programm sehr anfllig auf fehlende Dateien reagieren,
          also achte darauf, da alle bentigten Dateien (auch
          die EXE-Datei mu im gleichen Verzeichnis sein!) im
          Verzeichnis sind. Ich habe die Programme erfolgreich
          mit "Soulreaver", "Rogue Spear" und "GTA 2" ausprobiert
          und hatte keinerlei Probleme.
          Anmerkung --> Die Programme knnten auch mit ge-
                        dumpten EXE-Dateien funktionieren,
                        die mit der alten Safedisc Version
                        geschtzt waren.
          Wenn alles geklappt hat und du alles richtig gemacht
          hast, mtest du nun eine komplett lauffhige
          EXE-Datei haben!

    III.Schluwort / Thanks & Greetings / Autorkontakt

        Mit diesem Wissen sollte es dir jetzt mglich sein,
        ein beliebiges Safedisc-geschtztes Programm in
        zehn Minuten zu cracken (bin mal gespannt, wann die
        nchste Version kommt ;).

        Greetz und Thanks gehen an
        - alle AmoK Members
        - Black Check fr sein gutes Safedisc Tutorial
        - +Frog's Print fr FrogSice
        - G-RoM, Lorian und Stone fr ProcDump
        - tHeRaiN fr ADump
        - Numega fr SoftIce
        - C-Dilla fr Safedisc
        - Alle, die ich vergessen habe

        Lob und Kritik bitte an:
        tola@gmx.at

        Visit AmoK:
        travel.to/amok
        amok.notrix.de
        amok.mtv.to
